//
//  修饰模式通用代码.swift
//  ZhuangShiPattern
//
//  Created by mac on 2017/11/9.
//  Copyright © 2017年 RRC. All rights reserved.
//

import Foundation

//原始抽象构件，可以是一个接口或者是抽象类
protocol Component {
    //抽象方法
    func operate()
}

//具体构件：是最核心、最原始、最基本的接口或抽象类的实现，需要装饰的就是它
public class ConcreteComponent:Component{
    //具体实现
    func operate() {
        print("do Something")
    }
    
    
}

//修饰抽象类：实现接品或抽象方法，在它的属性里必然有一个private变量指向Component抽象构件
public class TYDecorator:Component{
    //指向原始抽象构件的变量
    private let component:Component
    //通过构造函数传递被修饰者
    init(component:Component) {
        self.component = component
    }
    //委托被修饰者执行
    func operate() {
        self.component.operate()
    }
    
    
}

//具体装饰角色
public class ConcreteDecoratorA:TYDecorator{
    //定义被修饰者
    override init(component: Component) {
        super.init(component: component)
    }
    //定义自己的修饰方法
    func method1(){
        print("method1 修饰")
    }
    //重写父灰的operation方法
    override func operate() {
        self.method1()
        super.operate()
    }
}

public class ConcreteDecoratorB:TYDecorator{
    //定义被修饰者
    override init(component: Component) {
        super.init(component: component)
    }
    //定义自己的修饰方法
    func method2(){
        print("method2 修饰")
    }
    //重写父灰的operation方法
    override func operate() {
        
        super.operate()
        self.method2()
    }
    /**
     注间：原始方法和装饰方法的执行顺序在具体的装饰类是固定的，可以通过方法重载实现多种执行顺序。
     */
}

//使用场景类
public class Client{
    public static func main(args:[String]){
        
        var component:Component = ConcreteComponent()
        //第一次修饰
        component = ConcreteDecoratorA(component: component)
        //第二次修饰
        component = ConcreteDecoratorB(component: component)
        //修饰后运行
        component.operate()
        
    }
}

/**
 装饰模式的优点：
    1､装饰类和被装饰类可以独立发展，而不会相互耦合。如：Component类无须知道Decorator类，Decorator类是从外部扩展Component类的功能，而Decorator也不用知道具体的构件。
    2､装饰模式是继承关系的一个替代方案。装饰类Decorator,不管装饰多少层，返回的对象还是Component,实现的还是is-a的关系。
    3､装饰模式可以动态地扩展一个实现类的功能，这不需要多说，装饰模式的定义就是如此。
 缺点：
    多层装饰是比较复杂的。因此。尽量减少装饰类的数量，以便降低系统的复杂度。
 
 使用场景：
    1､需要扩展一个类的功能，或给一个类增加附加功能。
    2､需要动态地给一个对象增加功能，这些功能可以再动态地撤销。
    3､需要为一批的兄弟类进行改装或加装功能，当然是首选装饰模式。
 
 */

